package sg.edu.nus.iss.billing.controller;

import static sg.edu.nus.iss.billing.localization.MessageKeyManager.getMessage;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import sg.edu.nus.iss.billing.constant.ErrorCodeConstants;
import sg.edu.nus.iss.billing.datastore.DBFactory;
import sg.edu.nus.iss.billing.datastore.IDataStore;
import sg.edu.nus.iss.billing.datastore.impl.Selector;
import sg.edu.nus.iss.billing.entity.RecordState;
import sg.edu.nus.iss.billing.entity.service.CableTVService;
import sg.edu.nus.iss.billing.entity.service.DigitalVoiceService;
import sg.edu.nus.iss.billing.entity.service.MobileVoiceService;
import sg.edu.nus.iss.billing.entity.service.PackageService;
import sg.edu.nus.iss.billing.entity.service.Service;
import sg.edu.nus.iss.billing.entity.service.ValueAddedService;
import sg.edu.nus.iss.billing.entity.service.ValueAddedService.ServiceType;
import sg.edu.nus.iss.billing.exception.ControllerException;
import sg.edu.nus.iss.billing.exception.DataStoreException;
import sg.edu.nus.iss.billing.localization.MessageKeyManager;


public class ServiceController {

	private IDataStore dataStorage;

	public ServiceController() {
		dataStorage = DBFactory.instance().getSDStore();
	}

	public List<Service> getAllServices() throws ControllerException {
		List<Service> serviceList = new ArrayList<Service>();
		try {
			serviceList = dataStorage.loadObjectsByType(Service.class);
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
		if(serviceList!=null)Collections.sort(serviceList);
		return serviceList;
	}
	
	public List<MobileVoiceService> getAllMobileVoiceServices() throws ControllerException {
		List<MobileVoiceService> serviceList = new ArrayList<MobileVoiceService>();
		try {
			serviceList = dataStorage.loadObjectsByType(MobileVoiceService.class);
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
		if(serviceList!=null)Collections.sort(serviceList);
		return serviceList;
	}
	
	public List<DigitalVoiceService> getAllDigitalVoiceServices() throws ControllerException {
		List<DigitalVoiceService> serviceList = new ArrayList<DigitalVoiceService>();
		try {
			serviceList = dataStorage.loadObjectsByType(DigitalVoiceService.class);
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
		if(serviceList!=null)Collections.sort(serviceList);
		return serviceList;
	}
	
	public List<CableTVService> getAllCableTVServices() throws ControllerException {
		List<CableTVService> serviceList = new ArrayList<CableTVService>();
		try {
			serviceList = dataStorage.loadObjectsByType(CableTVService.class);
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
		if(serviceList!=null)Collections.sort(serviceList);
		return serviceList;
	}
	
	public List<ValueAddedService> getVAServicesByProductId(String productId) throws ControllerException {
		List<ValueAddedService> serviceList = new ArrayList<ValueAddedService>();
		Selector selector = new Selector();
		selector.eq("serviceProductID", productId).ne("type",ServiceType.BASIC).ne("active", RecordState.DELETED).ne("active", RecordState.INACTIVE);
		try {
			serviceList = dataStorage.loadObjectsBySelector(ValueAddedService.class, selector);
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
		if(serviceList!=null)Collections.sort(serviceList);
		return serviceList;
	}
	
	public List<ValueAddedService> getBasicServicesByProductId(String productId) throws ControllerException {
		List<ValueAddedService> serviceList = new ArrayList<ValueAddedService>();
		Selector selector = new Selector();
		selector.eq("serviceProductID", productId).ne("type",ServiceType.ADDTIONAL).ne("active", RecordState.DELETED).ne("active", RecordState.INACTIVE);
		try {
			serviceList = dataStorage.loadObjectsBySelector(ValueAddedService.class, selector);
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
		if(serviceList!=null)Collections.sort(serviceList);
		return serviceList;
	}
	
	
	


	public void addService(Service serviceObj) throws ControllerException {
		
		//throw exception latter
		if(serviceObj instanceof ValueAddedService){
			return;
		}
		String serviceProductID = null;
		Service existingService = null;
		try {
			
			serviceProductID = serviceObj.getServiceProductID();
			// check if username is exist
			existingService = getServiceByProductID(serviceProductID);
			if (existingService != null) {
				throw new ControllerException(
						ErrorCodeConstants.ERROR_USER_DUPLICATION,
						MessageKeyManager.getMessage("error.serviceDuplication"));
			}
			
			dataStorage.saveObject(serviceObj);
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
	}
	
	public void addVAService(Service serviceObj) throws ControllerException {
		
		//throw exception latter
		if(!(serviceObj instanceof ValueAddedService)){
			return;
		}
		
		String serviceProductID = null;
		Service existingService = null;
		try {
			
			serviceProductID = serviceObj.getServiceProductID();
			existingService = getServiceByProductID(serviceProductID);
			if (existingService == null) {
				throw new ControllerException(
						ErrorCodeConstants.ERROR_USER_DUPLICATION,
						MessageKeyManager.getMessage("error.packageservice.null"));
			}
			
			dataStorage.saveObject(serviceObj);
		} catch (DataStoreException e) {
			e.printStackTrace();
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
	}

	public void deleteService(Service serviceObj) throws ControllerException {
		try {
			// set service as disactive
			serviceObj.setActive(RecordState.DELETED);
			dataStorage.saveObject(serviceObj);
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
	}

	public void editService(Service serviceObj) throws ControllerException {
		try {
			dataStorage.saveObject(serviceObj);
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
	}
	
	Service getServiceByProductID(String serviceProductID) throws ControllerException {
		List<PackageService> serviceList = null;
		Service serviceObj = null;
		Selector selector = new Selector();
		selector.eq("serviceProductID", serviceProductID);
		try {
			serviceList = dataStorage.loadObjectsBySelector(PackageService.class, selector);
			
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
		if (serviceList != null && serviceList.size() > 0) {
			serviceObj = serviceList.get(0);
		}
		return serviceObj;
	}
	
	public Service getServiceById(String id) throws ControllerException {

		Service service = null;
		try {
			service = dataStorage.loadObjectByID(Service.class, id);
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE, getMessage("error.dataStore"));
		}
		return service;
	}

	public List<? extends Service> getAllPkgSvcs(PackageService svc) throws ControllerException {
		try {
			if(svc instanceof CableTVService)
				return getAllCableTVServices();
			else if(svc instanceof MobileVoiceService)
				return getAllMobileVoiceServices();
			else if (svc instanceof DigitalVoiceService)
				return getAllDigitalVoiceServices();
			else
				return null;//throw exception latter
			
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE, getMessage("error.dataStore"));
		}
	}
	
	public void deleteAllServices() throws ControllerException {
		try {
			dataStorage.deleteObjectsByType(Service.class);
		} catch (DataStoreException e) {
			throw new ControllerException(ErrorCodeConstants.ERROR_DATASTORE,
					MessageKeyManager.getMessage("error.dataStore"));
		}
		
	}
	
}
